﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AnimaGestionPersonnage.Utilities;
using AnimaGestionPersonnage.Component;
using AnimaGestionPersonnage.Properties;
using System.Collections;

namespace AnimaGestionPersonnage.Vue
{
    public partial class FormPFSpending : Form, ICharacterSaved
    {
        private String charFileName;
        private Form previousForm;
        private int state;
        private TypeSkill previousType = TypeSkill.Erreur;
        private List<BasicSkillComponent> basicSkillCompList = new List<BasicSkillComponent>();
        private List<PrimarySkillComponent> primarySkillCompList = new List<PrimarySkillComponent>();
        private List<SecondarySkillComponent> secondarySkillCompList = new List<SecondarySkillComponent>();
        private bool saved;
        private bool savedAsDone;

        public FormPFSpending()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Mon showDialog() pour tenir compte de si on ouvre ou non un nouveau personnage
        /// </summary>
        /// </summary>
        /// <param name="parent">la fenetre de depart</param>
        /// <param name="previous">la precedente fenetre</param>
        /// <param name="status">le status d'ouverture</param>
        /// <param name="fileName">le nom du fichier de ce personnage</param>
        /// <param name="savedAsState">l'etat de sauvegarde</param>
        public void ShowDialog(Form parent, Form previous, int status, String fileName, Boolean savedAsState)
        {
            charFileName = fileName;
            previousForm = previous;
            state = status;

            Utils.setTPAvailToSpend();

            switch (status)
            {
                case Utils.LOAD_STATE:
                    this.Text = "Édition de personnage : PF";
                    break;
                case Utils.NEW_STATE:
                    this.Text = "Création de personnage : PF";
                    break;
                default:
                    MessageBox.Show(this, "État non supporté.", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    break;
            }

            foreach (Weapon w in Utils.weaponList)
            {
                if (!w.Equals(Utils.charac.principalWeapon))
                {
                    switch (w.getRelation(Utils.charac.principalWeapon))
                    {
                        case WeaponRelations.Distincte:
                            checkedListBoxDistincte.Items.Add(w);
                            break;
                        case WeaponRelations.Mixte:
                            checkedListBoxMixte.Items.Add(w);
                            break;
                        case WeaponRelations.Similaire:
                            checkedListBoxSimilaire.Items.Add(w);
                            break;
                        case WeaponRelations.Erreur:
                        default:
                            break;
                    }
                }
            }
            checkedListBoxDistincte.Items.Add(WeaponTypes.MainsNues);
            checkedListBoxEntiere.Items.AddRange(new ArrayList(Settings.Default.WeaponTypes).ToArray());
            checkedListBoxEntiere.Items.RemoveAt((int)WeaponTypes.Aucun);
            checkedListBoxEntiere.Items.RemoveAt((int)WeaponTypes.Munition);
            checkedListBoxEntiere.Items.RemoveAt((int)WeaponTypes.MainsNues);
            checkedListBoxStyles.Items.AddRange(Utils.combatModuleList.ToArray());
            checkedListBoxTypique.Items.AddRange(Utils.weaponModuleList.ToArray());

            loadCharDataFromFile(status);
            characterSaved(savedAsState);

            base.ShowDialog(parent);
        }

        #region EVENTS BUTTONS

        private void quitButton_Click(object sender, EventArgs e)
        {
            Close();
        }

        /// <summary>
        /// Sauvegarde les donnees de la fenetre dans un fichier.
        /// </summary>
        private void saveButton_Click(object sender, EventArgs e)
        {
            if (saved)
            {
                MessageBox.Show(this, "Données déjà suavegardé.", "Sauvegarde", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else if (!savedAsDone)
            {
                saveFileDialogCharacter.FileName = charFileName;
                if (saveFileDialogCharacter.ShowDialog() == DialogResult.OK)
                {
                    charFileName = saveFileDialogCharacter.FileName;
                    Utils.saveCharacterInfo(this, charFileName);
                }
            }
            else
            {
                Utils.saveCharacterInfo(this, charFileName);
            }
        }

        private void buttonBack_Click(object sender, EventArgs e)
        {
            Form temp = Owner;
            Owner = previousForm;
            previousForm = temp;
            Close();
        }

        private void buttonNext_Click(object sender, EventArgs e)
        {

        }

        #endregion

        private void FormPFSpending_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = Utils.onCloseEvent(saved, this, previousForm, e);
        }

        #region Local Method

        /// <summary>
        /// active le bouton de sauvegarde et flag comme non sauvegarde
        /// </summary>
        public void dataChanged()
        {
            if (Utils.getCurrentState() != Utils.LOADING_STATE)
            {
                characterSaved(false);
            }
        }

        /// <summary>
        /// Affiche la fenetre d'ouverture de fichier puis charge le personnage selectionner
        /// </summary>
        /// <returns>le bouton clique dans la fenetre de choix de fichier</returns>
        private void loadCharDataFromFile(int state)
        {
            int currentStartPosSec = panelSecondarySkill.Height,
                currentStartPosCombat = panelMartial.Height,
                currentStartPosMystic = panelMystic.Height,
                currentStartPosPsychic = panelPsychic.Height,
                currentStartPosOther = panelOther.Height;

            this.SuspendLayout();

            if (state == Utils.NEW_STATE)
            {
                foreach (SecondarySkill skill in Utils.secondarySkillsList)
                {
                    secondarySkillCompList.Add(new SecondarySkillComponent(skill));
                    Utils.charac.secondarySkills.Add(skill);
                }

                foreach (BasicSkill skill in Utils.basicSkillsList)
                {
                    basicSkillCompList.Add(new BasicSkillComponent(skill));
                    Utils.charac.basicSkills.Add(skill);
                }

                foreach (PrimarySkill skill in Utils.primarySkillsList)
                {
                    primarySkillCompList.Add(new PrimarySkillComponent(skill));
                    Utils.charac.primarySkills.Add(skill);
                }
            }
            else
            {
                bool notFound;
                int tempState = Utils.getCurrentState();
                Utils.setCurrentState(Utils.LOADING_STATE);

                foreach (SecondarySkill skill in Utils.charac.secondarySkills)
                {
                    secondarySkillCompList.Add(new SecondarySkillComponent(skill));
                }
                foreach (BasicSkill skill in Utils.charac.basicSkills)
                {
                    basicSkillCompList.Add(new BasicSkillComponent(skill));
                }
                foreach (PrimarySkill skill in Utils.charac.primarySkills)
                {
                    primarySkillCompList.Add(new PrimarySkillComponent(skill));
                }
                foreach (CombatModule cm in Utils.charac.combatModule)
                {
                    notFound = true;
                    foreach (object o in checkedListBoxStyles.Items)
                    {
                        if (o.ToString().Equals(cm.ToString()))
                        {
                            checkedListBoxStyles.SetItemChecked(checkedListBoxStyles.Items.IndexOf(o), true);
                            notFound = false;
                            break;
                        }
                    }
                }
                foreach (TypicalModule tm in Utils.charac.weaponModule)
                {
                    notFound = true;
                    foreach (object o in checkedListBoxEntiere.Items)
                    {
                        if (o.ToString().Equals(tm.ToString()))
                        {
                            checkedListBoxEntiere.SetItemChecked(checkedListBoxEntiere.Items.IndexOf(o), true);
                            notFound = false;
                            break;
                        }
                    }
                    if (notFound)
                    {
                        foreach (object o in checkedListBoxTypique.Items)
                        {
                            if (o.ToString().Equals(tm.ToString()))
                            {
                                checkedListBoxTypique.SetItemChecked(checkedListBoxTypique.Items.IndexOf(o), true);
                                notFound = false;
                                break;
                            }
                        }
                    }
                    if (notFound)
                    {
                        if (new TypicalModule("Improvisé").Equals(tm))
                        {
                            checkBoxImprovise.Checked = true;
                        }
                    }
                }
                foreach (GeneralModule gm in Utils.charac.generalModule)
                {
                    notFound = true;
                    foreach (object o in checkedListBoxSimilaire.Items)
                    {
                        if (o.ToString().Equals(gm.ToString()))
                        {
                            checkedListBoxSimilaire.SetItemChecked(checkedListBoxSimilaire.Items.IndexOf(o), true);
                            notFound = false;
                            break;
                        }
                    }
                    if (notFound)
                    {
                        foreach (object o in checkedListBoxMixte.Items)
                        {
                            if (o.ToString().Equals(gm.ToString()))
                            {
                                checkedListBoxMixte.SetItemChecked(checkedListBoxMixte.Items.IndexOf(o), true);
                                notFound = false;
                                break;
                            }
                        }
                    }
                    if (notFound)
                    {
                        foreach (object o in checkedListBoxDistincte.Items)
                        {
                            if (o.ToString().Equals(gm.ToString()))
                            {
                                checkedListBoxDistincte.SetItemChecked(checkedListBoxDistincte.Items.IndexOf(o), true);
                                notFound = false;
                                break;
                            }
                        }
                    }
                }
                Utils.setCurrentState(tempState);
            }

            foreach (SecondarySkillComponent ssc in secondarySkillCompList)
            {
                if (previousType != ssc.getTypeSkill())
                {
                    Label labelComp = new Label();

                    labelComp.Text = "-----" + ssc.getTypeSkill() + "-----";
                    this.tabPageSecSkills.Controls.Add(labelComp);
                    labelComp.Location = new Point(0, currentStartPosSec);
                    previousType = ssc.getTypeSkill();
                    currentStartPosSec += labelComp.Height;
                }
                this.tabPageSecSkills.Controls.Add(ssc);
                ssc.Location = new Point(0, currentStartPosSec);
                currentStartPosSec += ssc.Height;
            }

            foreach (PrimarySkillComponent psc in primarySkillCompList)
            {
                switch (psc.getTypeSkill())
                {
                    case TypeSkill.Combat:
                        this.tabPageCombat.Controls.Add(psc);
                        psc.Location = new Point(0, currentStartPosCombat);
                        currentStartPosCombat += psc.Height;
                        break;
                    case TypeSkill.Mystique:
                        this.tabPageMystic.Controls.Add(psc);
                        psc.Location = new Point(0, currentStartPosMystic);
                        currentStartPosMystic += psc.Height;
                        break;
                    case TypeSkill.Psionique:
                        this.tabPagePsychic.Controls.Add(psc);
                        psc.Location = new Point(0, currentStartPosPsychic);
                        currentStartPosPsychic += psc.Height;
                        break;
                    case TypeSkill.Autre:
                        this.tabPageOther.Controls.Add(psc);
                        psc.Location = new Point(0, currentStartPosOther);
                        currentStartPosOther += psc.Height;
                        break;

                }
            }

            foreach (BasicSkillComponent bsc in basicSkillCompList)
            {
                switch (bsc.getTypeSkill())
                {
                    case TypeSkill.Combat:
                        this.tabPageCombat.Controls.Add(bsc);
                        bsc.Location = new Point(0, currentStartPosCombat);
                        currentStartPosCombat += bsc.Height;
                        break;
                    case TypeSkill.Mystique:
                        this.tabPageMystic.Controls.Add(bsc);
                        bsc.Location = new Point(0, currentStartPosMystic);
                        currentStartPosMystic += bsc.Height;
                        break;
                    case TypeSkill.Psionique:
                        this.tabPagePsychic.Controls.Add(bsc);
                        bsc.Location = new Point(0, currentStartPosPsychic);
                        currentStartPosPsychic += bsc.Height;
                        break;
                    case TypeSkill.Autre:
                        this.tabPageOther.Controls.Add(bsc);
                        bsc.Location = new Point(0, currentStartPosOther);
                        currentStartPosOther += bsc.Height;
                        break;

                }
            }

            groupBoxCombatModule.Location = new Point(0, currentStartPosCombat);
            currentStartPosCombat += groupBoxCombatModule.Height;


            setLabelTPLeft();
            setLabelNaturalBonusLeft();
        }

        /// <summary>
        /// Affiche le nombre de PF restant au personnage
        /// </summary>
        public void setLabelTPLeft()
        {
            SuspendLayout();
            labelTPLeftSec.Text = Convert.ToString(Utils.charac.TPAvail);
            labelTPLeftCombat.Text = Convert.ToString(Utils.charac.TPAvail);
            labelTPLeftMystic.Text = Convert.ToString(Utils.charac.TPAvail);
            labelTPLeftPsy.Text = Convert.ToString(Utils.charac.TPAvail);
            labelTPLeftOther.Text = Convert.ToString(Utils.charac.TPAvail);
            labelMartialLimit.Text = Convert.ToString(Utils.tpCombat);
            labelMysticLimit.Text = Convert.ToString(Utils.tpMystic);
            labelPsychicLimit.Text = Convert.ToString(Utils.tpPsychic);
            ResumeLayout();
            dataChanged();
        }

        /// <summary>
        /// Affiche le nombre de bonus naturel restant
        /// </summary>
        public void setLabelNaturalBonusLeft()
        {
            SuspendLayout();
            labelNaturalBonusLeft.Text = Convert.ToString(Utils.charac.naturalBonusAvail);
            ResumeLayout();
            dataChanged();
        }

        public void characterSaved(bool isSaved)
        {
            saved = isSaved;
            if (savedAsDone != true)
                savedAsDone = isSaved;
            SuspendLayout();
            saveButton.Enabled = !isSaved;
            ResumeLayout();
        }

        /// <summary>
        /// Enleve le module de sa liste selon le type de classe de module
        /// </summary>
        /// <param name="module">le modue a enlever</param>
        #region void removeModule(module)
        private void removeModule(GeneralModule module)
        {
            if (Utils.getCurrentState() != Utils.LOADING_STATE)
            {
                Utils.charac.generalModule.Remove(module);
                Utils.charac.TPAvail += module.cost;
                Utils.setTPSpendings(TypeSkill.Combat, -module.cost);
            }
        }
        private void removeModule(TypicalModule module)
        {
            if (Utils.getCurrentState() != Utils.LOADING_STATE)
            {
                Utils.charac.weaponModule.Remove(module);
                Utils.charac.TPAvail += module.cost;
                Utils.setTPSpendings(TypeSkill.Combat, -module.cost);
            }
        }
        private void removeModule(CombatModule module)
        {
            if (Utils.getCurrentState() != Utils.LOADING_STATE)
            {
                Utils.charac.combatModule.Remove(module);
                Utils.charac.TPAvail += module.cost;
                Utils.setTPSpendings(TypeSkill.Combat, -module.cost);
            }
        }
        #endregion

        /// <summary>
        /// Ajoute un module a sa liste selon le type de classe
        /// </summary>
        /// <param name="module">le module a ajouter</param>
        #region void addModule(module)
        private void addModule(GeneralModule module)
        {
            if (Utils.getCurrentState() != Utils.LOADING_STATE)
            {
                Utils.charac.generalModule.Add(module);
                Utils.charac.TPAvail -= module.cost;
                Utils.setTPSpendings(module.type, module.cost);
            }
        }
        private void addModule(TypicalModule module)
        {
            if (Utils.getCurrentState() != Utils.LOADING_STATE)
            {
                Utils.charac.weaponModule.Add(module);
                Utils.charac.TPAvail -= module.cost;
                Utils.setTPSpendings(module.type, module.cost);
            }
        }
        private void addModule(CombatModule module)
        {
            if (Utils.getCurrentState() != Utils.LOADING_STATE)
            {
                Utils.charac.combatModule.Add(module);
                Utils.charac.TPAvail -= module.cost;
                Utils.setTPSpendings(module.type, module.cost);
            }
        }
        #endregion

        #endregion

        #region Events Elements

        private void checkedListBoxSimilaire_SelectedIndexChanged(object sender, EventArgs e)
        {
            GeneralModule tempMod = new GeneralModule(Utils.getWeapon(checkedListBoxSimilaire.SelectedItem.ToString()), WeaponRelations.Similaire);


            if (Utils.charac.generalModule.Contains(tempMod))
            {
                removeModule(tempMod);
            }
            if (this.checkedListBoxSimilaire.GetItemChecked(this.checkedListBoxSimilaire.SelectedIndex) == true)
            {
                if (Utils.isValidSpendig(tempMod))
                {
                    addModule(tempMod);
                }
                else
                {
                    checkedListBoxSimilaire.SetItemChecked(this.checkedListBoxSimilaire.SelectedIndex, false);
                }
            }
            setLabelTPLeft();
        }

        private void checkedListBoxMixte_SelectedIndexChanged(object sender, EventArgs e)
        {
            GeneralModule tempMod = new GeneralModule(Utils.getWeapon(checkedListBoxMixte.SelectedItem.ToString()), WeaponRelations.Mixte);

            if (Utils.charac.generalModule.Contains(tempMod))
            {
                removeModule(tempMod);
            }
            if (this.checkedListBoxMixte.GetItemChecked(this.checkedListBoxMixte.SelectedIndex) == true)
            {
                if (Utils.isValidSpendig(tempMod))
                {
                    addModule(tempMod);
                }
                else
                {
                    checkedListBoxMixte.SetItemChecked(this.checkedListBoxMixte.SelectedIndex, false);
                }
            }
            setLabelTPLeft();
        }

        private void checkedListBoxDistincte_SelectedIndexChanged(object sender, EventArgs e)
        {
            GeneralModule tempMod = new GeneralModule(Utils.getWeapon(checkedListBoxDistincte.SelectedItem.ToString()), WeaponRelations.Distincte);

            if (Utils.charac.generalModule.Contains(tempMod))
            {
                removeModule(tempMod);
            }
            if (this.checkedListBoxDistincte.GetItemChecked(this.checkedListBoxDistincte.SelectedIndex) == true)
            {
                if (Utils.isValidSpendig(tempMod))
                {
                    addModule(tempMod);
                }
                else
                {
                    checkedListBoxDistincte.SetItemChecked(this.checkedListBoxDistincte.SelectedIndex, false);
                }
            }
            setLabelTPLeft();
        }

        private void checkedListBoxEntiere_SelectedIndexChanged(object sender, EventArgs e)
        {
            TypicalModule tempModule = new TypicalModule(this.checkedListBoxEntiere.SelectedItem.ToString());
            tempModule.cost = 50;

            if (Utils.charac.weaponModule.Contains(tempModule))
            {
                removeModule(tempModule);
            }
            if (this.checkedListBoxEntiere.GetItemChecked(this.checkedListBoxEntiere.SelectedIndex) == true)
            {
                if (Utils.isValidSpendig(tempModule))
                {
                    addModule(tempModule);
                }
                else
                {
                    checkedListBoxEntiere.SetItemChecked(this.checkedListBoxEntiere.SelectedIndex, false);
                }
            }
            setLabelTPLeft();
        }

        private void checkedListBoxTypique_SelectedIndexChanged(object sender, EventArgs e)
        {
            TypicalModule tempModule = Utils.getTypicalModule(this.checkedListBoxTypique.SelectedItem.ToString());

            if (Utils.charac.weaponModule.Contains(tempModule))
            {
                removeModule(tempModule);
            }
            if (this.checkedListBoxTypique.GetItemChecked(this.checkedListBoxTypique.SelectedIndex) == true)
            {
                if (Utils.isValidSpendig(tempModule))
                {
                    addModule(tempModule);
                }
                else
                {
                    checkedListBoxTypique.SetItemChecked(this.checkedListBoxTypique.SelectedIndex, false);
                }
            }
            setLabelTPLeft();
        }

        private void checkedListBoxStyles_SelectedIndexChanged(object sender, EventArgs e)
        {
            CombatModule tempModule = Utils.getCombatModule(this.checkedListBoxStyles.SelectedItem.ToString());

            if (Utils.charac.combatModule.Contains(tempModule))
            {
                removeModule(tempModule);
            }
            if (this.checkedListBoxStyles.GetItemChecked(this.checkedListBoxStyles.SelectedIndex) == true)
            {
                if (Utils.isValidSpendig(tempModule))
                {
                    addModule(tempModule);
                }
                else
                {
                    checkedListBoxStyles.SetItemChecked(this.checkedListBoxStyles.SelectedIndex, false);
                }
            }
            setLabelTPLeft();
        }

        private void checkBoxImprovise_CheckedChanged(object sender, EventArgs e)
        {
            TypicalModule tempModule = new TypicalModule("Improvisé");
            tempModule.cost = 50;

            if (Utils.charac.weaponModule.Contains(tempModule))
            {
                removeModule(tempModule);
            }
            if (this.checkBoxImprovise.Checked == true)
            {
                if (Utils.isValidSpendig(tempModule))
                {
                    addModule(tempModule);
                }
                else
                {
                    checkBoxImprovise.Checked = false;
                }
            }
            setLabelTPLeft();
        }

        #endregion
    }
}
